// Decompiled on 周六 2月 22 19:31:49 CST 2025 with Zomboid Decompiler v0.1.3 using Vineflower.
package zombie.core.Collections;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.AbstractCollection;
import java.util.AbstractSet;
import java.util.Collection;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicLongFieldUpdater;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
import sun.misc.Unsafe;

public class NonBlockingHashtable<TypeK, TypeV> extends Dictionary<TypeK, TypeV> implements ConcurrentMap<TypeK, TypeV>, Cloneable, Serializable {
    private static final long serialVersionUID = 1234123412341234123L;
    private static final int REPROBE_LIMIT = 10;
    private static final Unsafe _unsafe = UtilUnsafe.getUnsafe();
    private static final int _Obase = _unsafe.arrayBaseOffset(Object[].class);
    private static final int _Oscale = _unsafe.arrayIndexScale(Object[].class);
    private static final long _kvs_offset;
    private transient Object[] _kvs;
    private transient long _last_resize_milli;
    private static final int MIN_SIZE_LOG = 3;
    private static final int MIN_SIZE = 8;
    private static final Object NO_MATCH_OLD;
    private static final Object MATCH_ANY;
    private static final Object TOMBSTONE;
    private static final NonBlockingHashtable.Prime TOMBPRIME;
    private transient Counter _reprobes = new Counter();

    private static long rawIndex(Object[] object, int _int) {
        assert _int >= 0 && _int < object.length;

        return (long)(_Obase + _int * _Oscale);
    }

    private final boolean CAS_kvs(Object[] object0, Object[] object1) {
        return _unsafe.compareAndSwapObject(this, _kvs_offset, object0, object1);
    }

    private static final int hash(Object object) {
        int _int = object.hashCode();
        _int += _int << 15 ^ -12931;
        _int ^= _int >>> 10;
        _int += _int << 3;
        _int ^= _int >>> 6;
        _int += (_int << 2) + (_int << 14);
        return _int ^ _int >>> 16;
    }

    private static final NonBlockingHashtable.CHM chm(Object[] object) {
        return (NonBlockingHashtable.CHM)object[0];
    }

    private static final int[] hashes(Object[] object) {
        return (int[])object[1];
    }

    private static final int len(Object[] object) {
        return object.length - 2 >> 1;
    }

    private static final Object key(Object[] object, int _int) {
        return object[(_int << 1) + 2];
    }

    private static final Object val(Object[] object, int _int) {
        return object[(_int << 1) + 3];
    }

    private static final boolean CAS_key(Object[] object0, int _int, Object object1, Object object2) {
        return _unsafe.compareAndSwapObject(object0, rawIndex(object0, (_int << 1) + 2), object1, object2);
    }

    private static final boolean CAS_val(Object[] object0, int _int, Object object1, Object object2) {
        return _unsafe.compareAndSwapObject(object0, rawIndex(object0, (_int << 1) + 3), object1, object2);
    }

    public final void print() {
        System.out.println("=========");
        this.print2(this._kvs);
        System.out.println("=========");
    }

    private final void print(Object[] object0) {
        for (int _int = 0; _int < len(object0); _int++) {
            Object object1 = key(object0, _int);
            if (object1 != null) {
                String string0 = object1 == TOMBSTONE ? "XXX" : object1.toString();
                Object object2 = val(object0, _int);
                Object object3 = NonBlockingHashtable.Prime.unbox(object2);
                String string1 = object2 == object3 ? "" : "prime_";
                String string2 = object3 == TOMBSTONE ? "tombstone" : object3.toString();
                System.out.println(_int + " (" + string0 + "," + string1 + string2 + ")");
            }
        }

        Object[] object4 = chm(object0)._newkvs;
        if (object4 != null) {
            System.out.println("----");
            this.print(object4);
        }
    }

    private final void print2(Object[] object0) {
        for (int _int = 0; _int < len(object0); _int++) {
            Object object1 = key(object0, _int);
            Object object2 = val(object0, _int);
            Object object3 = NonBlockingHashtable.Prime.unbox(object2);
            if (object1 != null && object1 != TOMBSTONE && object2 != null && object3 != TOMBSTONE) {
                String string = object2 == object3 ? "" : "prime_";
                System.out.println(_int + " (" + object1 + "," + string + object2 + ")");
            }
        }

        Object[] object4 = chm(object0)._newkvs;
        if (object4 != null) {
            System.out.println("----");
            this.print2(object4);
        }
    }

    public long reprobes() {
        long _long = this._reprobes.get();
        this._reprobes = new Counter();
        return _long;
    }

    private static final int reprobe_limit(int _int) {
        return 10 + (_int >> 2);
    }

    public NonBlockingHashtable() {
        this(8);
    }

    public NonBlockingHashtable(int initial_sz) {
        this.initialize(initial_sz);
    }

    private final void initialize(int int0) {
        if (int0 < 0) {
            throw new IllegalArgumentException();
        } else {
            if (int0 > 1048576) {
                int0 = 1048576;
            }

            int int1 = 3;

            while (1 << int1 < int0 << 2) {
                int1++;
            }

            this._kvs = new Object[(1 << int1 << 1) + 2];
            this._kvs[0] = new NonBlockingHashtable.CHM(new Counter());
            this._kvs[1] = new int[1 << int1];
            this._last_resize_milli = System.currentTimeMillis();
        }
    }

    protected final void initialize() {
        this.initialize(8);
    }

    public int size() {
        return chm(this._kvs).size();
    }

    public boolean isEmpty() {
        return this.size() == 0;
    }

    public boolean containsKey(Object key) {
        return this.get(key) != null;
    }

    public boolean contains(Object val) {
        return this.containsValue(val);
    }

    public TypeV put(TypeK object0, TypeV object1) {
        return this.putIfMatch(object0, object1, NO_MATCH_OLD);
    }

    public TypeV putIfAbsent(TypeK object0, TypeV object1) {
        return this.putIfMatch(object0, object1, TOMBSTONE);
    }

    public TypeV remove(Object object) {
        return this.putIfMatch(object, TOMBSTONE, NO_MATCH_OLD);
    }

    public boolean remove(Object key, Object val) {
        return this.putIfMatch(key, TOMBSTONE, val) == val;
    }

    public TypeV replace(TypeK object0, TypeV object1) {
        return this.putIfMatch(object0, object1, MATCH_ANY);
    }

    public boolean replace(TypeK object1, TypeV object0, TypeV object2) {
        return this.putIfMatch(object1, object2, object0) == object0;
    }

    private final TypeV putIfMatch(Object object3, Object object0, Object object1) {
        if (object1 != null && object0 != null) {
            Object object2 = putIfMatch(this, this._kvs, object3, object0, object1);

            assert !(object2 instanceof NonBlockingHashtable.Prime);

            assert object2 != null;

            return (TypeV)(object2 == TOMBSTONE ? null : object2);
        } else {
            throw new NullPointerException();
        }
    }

    public void putAll(Map<? extends TypeK, ? extends TypeV> m) {
        for (Entry entry : m.entrySet()) {
            this.put((TypeK)entry.getKey(), (TypeV)entry.getValue());
        }
    }

    public void clear() {
        Object[] object = (new NonBlockingHashtable(8))._kvs;

        while (!this.CAS_kvs(this._kvs, object)) {
        }
    }

    public boolean containsValue(Object val) {
        if (val == null) {
            throw new NullPointerException();
        } else {
            for (Object object : this.values()) {
                if (object == val || object.equals(val)) {
                    return true;
                }
            }

            return false;
        }
    }

    protected void rehash() {
    }

    public Object clone() {
        try {
            NonBlockingHashtable nonBlockingHashtable0 = (NonBlockingHashtable)super.clone();
            nonBlockingHashtable0.clear();

            for (Object object0 : this.keySet()) {
                Object object1 = this.get(object0);
                nonBlockingHashtable0.put(object0, object1);
            }

            return nonBlockingHashtable0;
        } catch (CloneNotSupportedException cloneNotSupportedException) {
            throw new InternalError();
        }
    }

    public String toString() {
        Iterator iterator = this.entrySet().iterator();
        if (!iterator.hasNext()) {
            return "{}";
        } else {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append('{');

            while (true) {
                Entry entry = (Entry)iterator.next();
                Object object0 = entry.getKey();
                Object object1 = entry.getValue();
                stringBuilder.append(object0 == this ? "(this Map)" : object0);
                stringBuilder.append('=');
                stringBuilder.append(object1 == this ? "(this Map)" : object1);
                if (!iterator.hasNext()) {
                    return stringBuilder.append('}').toString();
                }

                stringBuilder.append(", ");
            }
        }
    }

    private static boolean keyeq(Object object1, Object object0, int[] int1, int int2, int int0) {
        return object1 == object0 || (int1[int2] == 0 || int1[int2] == int0) && object1 != TOMBSTONE && object0.equals(object1);
    }

    public TypeV get(Object object0) {
        int _int = hash(object0);
        Object object1 = get_impl(this, this._kvs, object0, _int);

        assert !(object1 instanceof NonBlockingHashtable.Prime);

        return (TypeV)object1;
    }

    private static final Object get_impl(NonBlockingHashtable nonBlockingHashtable, Object[] object0, Object object4, int int3) {
        int int0 = len(object0);
        NonBlockingHashtable.CHM cHM = chm(object0);
        int[] int1 = hashes(object0);
        int int2 = int3 & int0 - 1;
        int int4 = 0;

        while (true) {
            Object object1 = key(object0, int2);
            Object object2 = val(object0, int2);
            if (object1 == null) {
                return null;
            }

            Object[] object3 = cHM._newkvs;
            if (keyeq(object1, object4, int1, int2, int3)) {
                if (!(object2 instanceof NonBlockingHashtable.Prime)) {
                    return object2 == TOMBSTONE ? null : object2;
                }

                return get_impl(nonBlockingHashtable, cHM.copy_slot_and_check(nonBlockingHashtable, object0, int2, object4), object4, int3);
            }

            if (++int4 >= reprobe_limit(int0) || object4 == TOMBSTONE) {
                return object3 == null ? null : get_impl(nonBlockingHashtable, nonBlockingHashtable.help_copy(object3), object4, int3);
            }

            int2 = int2 + 1 & int0 - 1;
        }
    }

    private static final Object putIfMatch(NonBlockingHashtable nonBlockingHashtable, Object[] object3, Object object2, Object object0, Object object1) {
        assert object0 != null;

        assert !(object0 instanceof NonBlockingHashtable.Prime);

        assert !(object1 instanceof NonBlockingHashtable.Prime);

        int int0 = hash(object2);
        int int1 = len(object3);
        NonBlockingHashtable.CHM cHM = chm(object3);
        int[] int2 = hashes(object3);
        int int3 = int0 & int1 - 1;
        int int4 = 0;
        Object object4 = null;
        Object object5 = null;
        Object[] object6 = null;

        while (true) {
            object5 = val(object3, int3);
            object4 = key(object3, int3);
            if (object4 == null) {
                if (object0 == TOMBSTONE) {
                    return object0;
                }

                if (CAS_key(object3, int3, null, object2)) {
                    cHM._slots.add(1L);
                    int2[int3] = int0;
                    break;
                }

                object4 = key(object3, int3);

                assert object4 != null;
            }

            object6 = cHM._newkvs;
            if (!keyeq(object4, object2, int2, int3, int0)) {
                if (++int4 < reprobe_limit(int1) && object2 != TOMBSTONE) {
                    int3 = int3 + 1 & int1 - 1;
                    continue;
                }

                object6 = cHM.resize(nonBlockingHashtable, object3);
                if (object1 != null) {
                    nonBlockingHashtable.help_copy(object6);
                }

                return putIfMatch(nonBlockingHashtable, object6, object2, object0, object1);
            }
            break;
        }

        if (object0 == object5) {
            return object5;
        } else {
            if (object6 == null && (object5 == null && cHM.tableFull(int4, int1) || object5 instanceof NonBlockingHashtable.Prime)) {
                object6 = cHM.resize(nonBlockingHashtable, object3);
            }

            if (object6 != null) {
                return putIfMatch(nonBlockingHashtable, cHM.copy_slot_and_check(nonBlockingHashtable, object3, int3, object1), object2, object0, object1);
            } else {
                while ($assertionsDisabled || !(object5 instanceof NonBlockingHashtable.Prime)) {
                    if (object1 != NO_MATCH_OLD
                        && object5 != object1
                        && (object1 != MATCH_ANY || object5 == TOMBSTONE || object5 == null)
                        && (object5 != null || object1 != TOMBSTONE)
                        && (object1 == null || !object1.equals(object5))) {
                        return object5;
                    }

                    if (CAS_val(object3, int3, object5, object0)) {
                        if (object1 != null) {
                            if ((object5 == null || object5 == TOMBSTONE) && object0 != TOMBSTONE) {
                                cHM._size.add(1L);
                            }

                            if (object5 != null && object5 != TOMBSTONE && object0 == TOMBSTONE) {
                                cHM._size.add(-1L);
                            }
                        }

                        return object5 == null && object1 != null ? TOMBSTONE : object5;
                    }

                    object5 = val(object3, int3);
                    if (object5 instanceof NonBlockingHashtable.Prime) {
                        return putIfMatch(
                            nonBlockingHashtable, cHM.copy_slot_and_check(nonBlockingHashtable, object3, int3, object1), object2, object0, object1
                        );
                    }
                }

                throw new AssertionError();
            }
        }
    }

    private final Object[] help_copy(Object[] object1) {
        Object[] object0 = this._kvs;
        NonBlockingHashtable.CHM cHM = chm(object0);
        if (cHM._newkvs == null) {
            return object1;
        } else {
            cHM.help_copy_impl(this, object0, false);
            return object1;
        }
    }

    public Enumeration<TypeV> elements() {
        return new NonBlockingHashtable.SnapshotV();
    }

    public Collection<TypeV> values() {
        return new AbstractCollection<TypeV>() {
            public void clear() {
                NonBlockingHashtable.this.clear();
            }

            public int size() {
                return NonBlockingHashtable.this.size();
            }

            public boolean contains(Object object) {
                return NonBlockingHashtable.this.containsValue(object);
            }

            public Iterator<TypeV> iterator() {
                return NonBlockingHashtable.this.new SnapshotV();
            }
        };
    }

    public Enumeration<TypeK> keys() {
        return new NonBlockingHashtable.SnapshotK();
    }

    public Set<TypeK> keySet() {
        return new AbstractSet<TypeK>() {
            public void clear() {
                NonBlockingHashtable.this.clear();
            }

            public int size() {
                return NonBlockingHashtable.this.size();
            }

            public boolean contains(Object object) {
                return NonBlockingHashtable.this.containsKey(object);
            }

            public boolean remove(Object object) {
                return NonBlockingHashtable.this.remove(object) != null;
            }

            public Iterator<TypeK> iterator() {
                return NonBlockingHashtable.this.new SnapshotK();
            }
        };
    }

    public Set<Entry<TypeK, TypeV>> entrySet() {
        return new AbstractSet<Entry<TypeK, TypeV>>() {
            public void clear() {
                NonBlockingHashtable.this.clear();
            }

            public int size() {
                return NonBlockingHashtable.this.size();
            }

            public boolean remove(Object object) {
                return !(object instanceof Entry entry) ? false : NonBlockingHashtable.this.remove(entry.getKey(), entry.getValue());
            }

            public boolean contains(Object object0) {
                if (!(object0 instanceof Entry entry)) {
                    return false;
                } else {
                    Object object1 = NonBlockingHashtable.this.get(entry.getKey());
                    return object1.equals(entry.getValue());
                }
            }

            public Iterator<Entry<TypeK, TypeV>> iterator() {
                return NonBlockingHashtable.this.new SnapshotE();
            }
        };
    }

    private void writeObject(ObjectOutputStream objectOutputStream) throws IOException {
        objectOutputStream.defaultWriteObject();

        for (Object object0 : this.keySet()) {
            Object object1 = this.get(object0);
            objectOutputStream.writeObject(object0);
            objectOutputStream.writeObject(object1);
        }

        objectOutputStream.writeObject(null);
        objectOutputStream.writeObject(null);
    }

    private void readObject(ObjectInputStream objectInputStream) throws IOException, ClassNotFoundException {
        objectInputStream.defaultReadObject();
        this.initialize(8);

        while (true) {
            Object object0 = objectInputStream.readObject();
            Object object1 = objectInputStream.readObject();
            if (object0 == null) {
                return;
            }

            this.put((TypeK)object0, (TypeV)object1);
        }
    }

    static {
        Object object = null;

        try {
            object = NonBlockingHashtable.class.getDeclaredField("_kvs");
        } catch (NoSuchFieldException noSuchFieldException) {
            throw new RuntimeException(noSuchFieldException);
        }

        _kvs_offset = _unsafe.objectFieldOffset((Field)object);
        NO_MATCH_OLD = new Object();
        MATCH_ANY = new Object();
        TOMBSTONE = new Object();
        TOMBPRIME = new NonBlockingHashtable.Prime(TOMBSTONE);
    }

    private static final class CHM<TypeK, TypeV> {
        private final Counter _size;
        private final Counter _slots;
        volatile Object[] _newkvs;
        private final AtomicReferenceFieldUpdater<NonBlockingHashtable.CHM, Object[]> _newkvsUpdater = AtomicReferenceFieldUpdater.newUpdater(
            NonBlockingHashtable.CHM.class, Object[].class, "_newkvs"
        );
        volatile long _resizers;
        private static final AtomicLongFieldUpdater<NonBlockingHashtable.CHM> _resizerUpdater = AtomicLongFieldUpdater.newUpdater(
            NonBlockingHashtable.CHM.class, "_resizers"
        );
        volatile long _copyIdx = 0L;
        private static final AtomicLongFieldUpdater<NonBlockingHashtable.CHM> _copyIdxUpdater = AtomicLongFieldUpdater.newUpdater(
            NonBlockingHashtable.CHM.class, "_copyIdx"
        );
        volatile long _copyDone = 0L;
        private static final AtomicLongFieldUpdater<NonBlockingHashtable.CHM> _copyDoneUpdater = AtomicLongFieldUpdater.newUpdater(
            NonBlockingHashtable.CHM.class, "_copyDone"
        );

        public int size() {
            return (int)this._size.get();
        }

        public int slots() {
            return (int)this._slots.get();
        }

        boolean CAS_newkvs(Object[] object) {
            while (this._newkvs == null) {
                if (this._newkvsUpdater.compareAndSet(this, null, object)) {
                    return true;
                }
            }

            return false;
        }

        CHM(Counter counter) {
            this._size = counter;
            this._slots = new Counter();
        }

        private final boolean tableFull(int int1, int int0) {
            return int1 >= 10 && this._slots.estimate_get() >= (long)NonBlockingHashtable.reprobe_limit(int0);
        }

        private final Object[] resize(NonBlockingHashtable nonBlockingHashtable, Object[] object0) {
            assert NonBlockingHashtable.chm(object0) == this;

            Object[] object1 = this._newkvs;
            if (object1 != null) {
                return object1;
            } else {
                int int0 = NonBlockingHashtable.len(object0);
                int int1 = this.size();
                int int2 = int1;
                if (int1 >= int0 >> 2) {
                    int2 = int0 << 1;
                    if (int1 >= int0 >> 1) {
                        int2 = int0 << 2;
                    }
                }

                long long0 = System.currentTimeMillis();
                long long1 = 0L;
                if (int2 <= int0 && long0 <= nonBlockingHashtable._last_resize_milli + 10000L && this._slots.estimate_get() >= (long)(int1 << 1)) {
                    int2 = int0 << 1;
                }

                if (int2 < int0) {
                    int2 = int0;
                }

                int int3 = 3;

                while (1 << int3 < int2) {
                    int3++;
                }

                long long2 = this._resizers;

                while (!_resizerUpdater.compareAndSet(this, long2, long2 + 1L)) {
                    long2 = this._resizers;
                }

                int int4 = (1 << int3 << 1) + 4 << 3 >> 20;
                if (long2 >= 2L && int4 > 0) {
                    object1 = this._newkvs;
                    if (object1 != null) {
                        return object1;
                    }

                    try {
                        Thread.sleep((long)(8 * int4));
                    } catch (Exception exception) {
                    }
                }

                object1 = this._newkvs;
                if (object1 != null) {
                    return object1;
                } else {
                    object1 = new Object[(1 << int3 << 1) + 2];
                    object1[0] = new NonBlockingHashtable.CHM(this._size);
                    object1[1] = new int[1 << int3];
                    if (this._newkvs != null) {
                        return this._newkvs;
                    } else {
                        if (this.CAS_newkvs(object1)) {
                            nonBlockingHashtable.rehash();
                        } else {
                            object1 = this._newkvs;
                        }

                        return object1;
                    }
                }
            }
        }

        private final void help_copy_impl(NonBlockingHashtable nonBlockingHashtable, Object[] object0, boolean _boolean) {
            assert NonBlockingHashtable.chm(object0) == this;

            Object[] object1 = this._newkvs;

            assert object1 != null;

            int int0 = NonBlockingHashtable.len(object0);
            int int1 = Math.min(int0, 1024);
            int int2 = -1;
            int int3 = -9999;

            while (this._copyDone < (long)int0) {
                if (int2 == -1) {
                    int3 = (int)this._copyIdx;

                    while (int3 < int0 << 1 && !_copyIdxUpdater.compareAndSet(this, (long)int3, (long)(int3 + int1))) {
                        int3 = (int)this._copyIdx;
                    }

                    if (int3 >= int0 << 1) {
                        int2 = int3;
                    }
                }

                int int4 = 0;

                for (int int5 = 0; int5 < int1; int5++) {
                    if (this.copy_slot(nonBlockingHashtable, int3 + int5 & int0 - 1, object0, object1)) {
                        int4++;
                    }
                }

                if (int4 > 0) {
                    this.copy_check_and_promote(nonBlockingHashtable, object0, int4);
                }

                int3 += int1;
                if (!_boolean && int2 == -1) {
                    return;
                }
            }

            this.copy_check_and_promote(nonBlockingHashtable, object0, 0);
        }

        private final Object[] copy_slot_and_check(NonBlockingHashtable nonBlockingHashtable, Object[] object0, int _int, Object object2) {
            assert NonBlockingHashtable.chm(object0) == this;

            Object[] object1 = this._newkvs;

            assert object1 != null;

            if (this.copy_slot(nonBlockingHashtable, _int, object0, this._newkvs)) {
                this.copy_check_and_promote(nonBlockingHashtable, object0, 1);
            }

            return object2 == null ? object1 : nonBlockingHashtable.help_copy(object1);
        }

        private final void copy_check_and_promote(NonBlockingHashtable nonBlockingHashtable, Object[] object, int int1) {
            assert NonBlockingHashtable.chm(object) == this;

            int int0 = NonBlockingHashtable.len(object);
            long _long = this._copyDone;

            assert _long + (long)int1 <= (long)int0;

            if (int1 > 0) {
                while (!_copyDoneUpdater.compareAndSet(this, _long, _long + (long)int1)) {
                    _long = this._copyDone;

                    assert _long + (long)int1 <= (long)int0;
                }
            }

            if (_long + (long)int1 == (long)int0 && nonBlockingHashtable._kvs == object && nonBlockingHashtable.CAS_kvs(object, this._newkvs)) {
                nonBlockingHashtable._last_resize_milli = System.currentTimeMillis();
            }
        }

        private boolean copy_slot(NonBlockingHashtable nonBlockingHashtable, int _int, Object[] object1, Object[] object4) {
            Object object0;
            while ((object0 = NonBlockingHashtable.key(object1, _int)) == null) {
                NonBlockingHashtable.CAS_key(object1, _int, null, NonBlockingHashtable.TOMBSTONE);
            }

            Object object2;
            for (object2 = NonBlockingHashtable.val(object1, _int);
                !(object2 instanceof NonBlockingHashtable.Prime);
                object2 = NonBlockingHashtable.val(object1, _int)
            ) {
                NonBlockingHashtable.Prime prime = object2 != null && object2 != NonBlockingHashtable.TOMBSTONE
                    ? new NonBlockingHashtable.Prime(object2)
                    : NonBlockingHashtable.TOMBPRIME;
                if (NonBlockingHashtable.CAS_val(object1, _int, object2, prime)) {
                    if (prime == NonBlockingHashtable.TOMBPRIME) {
                        return true;
                    }

                    object2 = prime;
                    break;
                }
            }

            if (object2 == NonBlockingHashtable.TOMBPRIME) {
                return false;
            } else {
                Object object3 = ((NonBlockingHashtable.Prime)object2)._V;

                assert object3 != NonBlockingHashtable.TOMBSTONE;

                boolean _boolean = NonBlockingHashtable.putIfMatch(nonBlockingHashtable, object4, object0, object3, null) == null;

                while (!NonBlockingHashtable.CAS_val(object1, _int, object2, NonBlockingHashtable.TOMBPRIME)) {
                    object2 = NonBlockingHashtable.val(object1, _int);
                }

                return _boolean;
            }
        }
    }

    private class NBHMEntry extends AbstractEntry<TypeK, TypeV> {
        NBHMEntry(TypeK object0, TypeV object1) {
            super((TypeK)object0, (TypeV)object1);
        }

        public TypeV setValue(TypeV object) {
            if (object == null) {
                throw new NullPointerException();
            } else {
                this._val = (TypeV)object;
                return NonBlockingHashtable.this.put(this._key, (TypeV)object);
            }
        }
    }

    private static final class Prime {
        final Object _V;

        Prime(Object object) {
            this._V = object;
        }

        static Object unbox(Object object) {
            return object instanceof NonBlockingHashtable.Prime ? ((NonBlockingHashtable.Prime)object)._V : object;
        }
    }

    private class SnapshotE implements Iterator<Entry<TypeK, TypeV>> {
        final NonBlockingHashtable<TypeK, TypeV>.SnapshotV _ss = NonBlockingHashtable.this.new SnapshotV();

        public SnapshotE() {
        }

        public void remove() {
            this._ss.remove();
        }

        public Entry<TypeK, TypeV> next() {
            this._ss.next();
            return NonBlockingHashtable.this.new NBHMEntry(this._ss._prevK, this._ss._prevV);
        }

        public boolean hasNext() {
            return this._ss.hasNext();
        }
    }

    private class SnapshotK implements Iterator<TypeK>, Enumeration<TypeK> {
        final NonBlockingHashtable<TypeK, TypeV>.SnapshotV _ss = NonBlockingHashtable.this.new SnapshotV();

        public SnapshotK() {
        }

        public void remove() {
            this._ss.remove();
        }

        public TypeK next() {
            this._ss.next();
            return (TypeK)this._ss._prevK;
        }

        public boolean hasNext() {
            return this._ss.hasNext();
        }

        public TypeK nextElement() {
            return (TypeK)this.next();
        }

        public boolean hasMoreElements() {
            return this.hasNext();
        }
    }

    private class SnapshotV implements Iterator<TypeV>, Enumeration<TypeV> {
        final Object[] _sskvs;
        private int _idx;
        private Object _nextK;
        private Object _prevK;
        private TypeV _nextV;
        private TypeV _prevV;

        public SnapshotV() {
            while (true) {
                Object[] object = NonBlockingHashtable.this._kvs;
                NonBlockingHashtable.CHM cHM = NonBlockingHashtable.chm(object);
                if (cHM._newkvs == null) {
                    this._sskvs = object;
                    this.next();
                    return;
                }

                cHM.help_copy_impl(NonBlockingHashtable.this, object, true);
            }
        }

        int length() {
            return NonBlockingHashtable.len(this._sskvs);
        }

        Object key(int _int) {
            return NonBlockingHashtable.key(this._sskvs, _int);
        }

        public boolean hasNext() {
            return this._nextV != null;
        }

        public TypeV next() {
            if (this._idx != 0 && this._nextV == null) {
                throw new NoSuchElementException();
            } else {
                this._prevK = this._nextK;
                this._prevV = this._nextV;
                this._nextV = null;

                while (this._idx < this.length()) {
                    this._nextK = this.key(this._idx++);
                    if (this._nextK != null
                        && this._nextK != NonBlockingHashtable.TOMBSTONE
                        && (this._nextV = NonBlockingHashtable.this.get(this._nextK)) != null) {
                        break;
                    }
                }

                return this._prevV;
            }
        }

        public void remove() {
            if (this._prevV == null) {
                throw new IllegalStateException();
            } else {
                NonBlockingHashtable.putIfMatch(NonBlockingHashtable.this, this._sskvs, this._prevK, NonBlockingHashtable.TOMBSTONE, this._prevV);
                this._prevV = null;
            }
        }

        public TypeV nextElement() {
            return (TypeV)this.next();
        }

        public boolean hasMoreElements() {
            return this.hasNext();
        }
    }
}
